package me.zhengjie.minbearwcs.serivce.mission.storageProcessor.locker.Floor5Or6.impl;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.minbearwcs.dao.outbound.inf.OutboundDao;
import me.zhengjie.minbearwcs.dao.storage.inf.SmallStorageDao;
import me.zhengjie.minbearwcs.dao.storage.inf.StorageDao;
import me.zhengjie.minbearwcs.entity.DTO.transfer.Tuple;
import me.zhengjie.minbearwcs.entity.PO.wcs.outbound.stockUp.PalletMediumStorageSearchPo;
import me.zhengjie.minbearwcs.entity.PO.wcs.storage.SmallStorage;
import me.zhengjie.minbearwcs.entity.PO.wcs.storage.type.StorageType;
import me.zhengjie.minbearwcs.serivce.mission.storageProcessor.locker.Floor5Or6.Storage5Or6FloorPassSelector;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@Component
@RequiredArgsConstructor
public class Storage5Or6FloorPassSelectorImpl implements Storage5Or6FloorPassSelector {

    private final OutboundDao outboundDao;
    private final StorageDao storageDao;
    private final SmallStorageDao smallStorageDao;

    @Override
    public Tuple<String> selectPass(String smallStorageCode) {
        StorageType storageType = storageDao.selectStorageTypeBySmallStorage(smallStorageCode);

        HashSet<StorageType> storageTypeSet = new HashSet<>();
        storageTypeSet.add(StorageType.STORAGE_AREA_5F);
        storageTypeSet.add(StorageType.STORAGE_AREA_6F);
        storageTypeSet.add(StorageType.WAIT_SORT_AREA_5F);
        storageTypeSet.add(StorageType.WAIT_SORT_AREA_6F);
        storageTypeSet.add(StorageType.WHARF_1F);
        storageTypeSet.add(StorageType.STORAGE_AREA_3F);
        storageTypeSet.add(StorageType.STORAGE_AREA_4F);

        if (!storageTypeSet.contains(storageType)){
            return Tuple.tuple(null, false);
        }

        SmallStorage smallStorage = smallStorageDao.selectBySmallStorage(smallStorageCode);
        List<PalletMediumStorageSearchPo> palletMediumStorageSearchPoList = outboundDao.selectPalletMediumStorage(smallStorage.getMediumStorageCode());

        PalletMediumStorageSearchPo nowPalletMediumStorageSearchPo = palletMediumStorageSearchPoList.stream()
                .filter(a -> smallStorageCode.equals(a.getSmallStorageCode()))
                .findFirst()
                .get();

        String materialCode = nowPalletMediumStorageSearchPo.getMaterialCode();


        // 几个出口
        long enterCount = palletMediumStorageSearchPoList
                .stream()
                .filter(a -> a.getIsEntrance() == 1)
                .count();

        if (enterCount == 2) {
            // 多少个批次
            long batchCount = palletMediumStorageSearchPoList
                    .stream()
                    .filter(a -> a.getMaterialCode() != null && a.getBatchCode() != null && a.getInboundOrderCode() != null)
                    .map(a -> a.getMaterialCode() + a.getBatchCode() + a.getInboundOrderCode())
                    .distinct()
                    .count();

            if (batchCount <= 1) {
                return getMaxEnter(palletMediumStorageSearchPoList);
            } else if (batchCount == 2) {
                // 判断哪边是入口
                Optional<PalletMediumStorageSearchPo> min = palletMediumStorageSearchPoList
                        .stream()
                        .filter(a -> a.getPalletCode() != null)
                        .min(Comparator.comparingInt(PalletMediumStorageSearchPo::getColumnNum));

                Optional<PalletMediumStorageSearchPo> max = palletMediumStorageSearchPoList
                        .stream()
                        .filter(a -> a.getPalletCode() != null)
                        .max(Comparator.comparingInt(PalletMediumStorageSearchPo::getColumnNum));

                if (min.isPresent() && max.isPresent()) {
                    PalletMediumStorageSearchPo minTemp = min.get();
                    PalletMediumStorageSearchPo maxTemp = max.get();

                    if (materialCode.equals(minTemp.getMaterialCode()) && materialCode.equals(maxTemp.getMaterialCode())) {
                        // 物料一样，进行更深层次判断
                        if (maxTemp.getMaterialCode().equals(nowPalletMediumStorageSearchPo.getMaterialCode()) &&
                                maxTemp.getInboundOrderCode().equals(nowPalletMediumStorageSearchPo.getInboundOrderCode()) &&
                                maxTemp.getBatchCode().equals(nowPalletMediumStorageSearchPo.getBatchCode())) {
                            return getMaxEnter(palletMediumStorageSearchPoList);
                        } else {
                            return getMinEnter(palletMediumStorageSearchPoList);
                        }
                    } else if (minTemp.getMaterialCode().equals(materialCode)) {
                        // 从前往后
                        return getMinEnter(palletMediumStorageSearchPoList);
                    } else if (maxTemp.getMaterialCode().equals(materialCode)) {
                        // 从后往前
                        return getMaxEnter(palletMediumStorageSearchPoList);
                    }


                }

            }


        } else if (enterCount == 1) {
            List<PalletMediumStorageSearchPo> collect = palletMediumStorageSearchPoList
                    .stream()
                    .filter(a -> a.getIsEntrance() == 1)
                    .collect(Collectors.toList());

            PalletMediumStorageSearchPo enter = collect.get(0);
            return Tuple.tuple(enter.getSmallStorageCode(), true);
        }


        return Tuple.tuple(null, false);
    }


    public Tuple<String> getMinEnter(List<PalletMediumStorageSearchPo> palletMediumStorageSearchPoList) {
        String enter = palletMediumStorageSearchPoList
                .stream()
                .filter(a -> a.getIsEntrance() == 1)
                .min(Comparator.comparingInt(PalletMediumStorageSearchPo::getColumnNum))
                .get()
                .getSmallStorageCode();

        return Tuple.tuple(enter, true);
    }

    public Tuple<String> getMaxEnter(List<PalletMediumStorageSearchPo> palletMediumStorageSearchPoList) {
        String enter = palletMediumStorageSearchPoList
                .stream()
                .filter(a -> a.getIsEntrance() == 1)
                .max(Comparator.comparingInt(PalletMediumStorageSearchPo::getColumnNum))
                .get()
                .getSmallStorageCode();

        return Tuple.tuple(enter, true);
    }

    private boolean judgeCanOutFrontToBack(SmallStorage shiftingSmallStorage, List<SmallStorage> smallStorageList) {
        boolean oneEnterCanOut = true;
        for (int i = 0; i < smallStorageList.size(); i++) {
            SmallStorage tempStorage = smallStorageList.get(i);
            if (shiftingSmallStorage.getSmallStorageCode().equals(tempStorage.getSmallStorageCode())) {
                break;
            }

            if (tempStorage.getOutboundFreezePallet() != null) continue;

            if (tempStorage.getPalletCode() != null || tempStorage.getInboundFreezePallet() != null) {
                oneEnterCanOut &= false;
            }
        }
        return oneEnterCanOut;
    }

    private boolean judgeCanOutBackToFront(SmallStorage shiftingSmallStorage, List<SmallStorage> smallStorageList) {
        boolean oneEnterCanOut = true;
        for (int j = smallStorageList.size() - 1; j >= 0; j--) {
            SmallStorage tempStorage = smallStorageList.get(j);
            if (shiftingSmallStorage.getSmallStorageCode().equals(tempStorage.getSmallStorageCode())) {
                break;
            }

            if (tempStorage.getOutboundFreezePallet() != null) continue;

            if (tempStorage.getPalletCode() != null || tempStorage.getInboundFreezePallet() != null) {
                oneEnterCanOut &= false;
            }
        }
        return oneEnterCanOut;
    }
}
